tipc: move received discovery data evaluation inside node.c
authorJon Paul Maloy <jon.maloy@ericsson.com>
Thu, 30 Jul 2015 22:24:22 +0000 (18:24 -0400)
committerDavid S. Miller <davem@davemloft.net>
Fri, 31 Jul 2015 00:25:14 +0000 (17:25 -0700)
The node lock is currently grabbed and and released in the function
tipc_disc_rcv() in the file discover.c. As a preparation for the next
commits, we need to move this node lock handling, along with the code
area it is covering, to node.c.

This commit introduces this change.

Tested-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/tipc/discover.c
net/tipc/node.c
net/tipc/node.h

index 164d08907d6f67e67f65fc3de05d965319fe8815..d14e0a4aa9af900a7ace6855ab91eb2bcc901641 100644 (file)
@@ -120,29 +120,24 @@ static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr,
  * @buf: buffer containing message
  * @bearer: bearer that message arrived on
  */
-void tipc_disc_rcv(struct net *net, struct sk_buff *buf,
+void tipc_disc_rcv(struct net *net, struct sk_buff *skb,
                   struct tipc_bearer *bearer)
 {
        struct tipc_net *tn = net_generic(net, tipc_net_id);
-       struct tipc_node *node;
        struct tipc_media_addr maddr;
-       struct sk_buff *rbuf;
-       struct tipc_msg *msg = buf_msg(buf);
-       u32 ddom = msg_dest_domain(msg);
-       u32 onode = msg_prevnode(msg);
-       u32 net_id = msg_bc_netid(msg);
-       u32 mtyp = msg_type(msg);
-       u32 signature = msg_node_sig(msg);
-       u16 caps = msg_node_capabilities(msg);
-       bool addr_match = false;
-       bool sign_match = false;
-       bool link_up = false;
-       bool accept_addr = false;
-       bool accept_sign = false;
+       struct sk_buff *rskb;
+       struct tipc_msg *hdr = buf_msg(skb);
+       u32 ddom = msg_dest_domain(hdr);
+       u32 onode = msg_prevnode(hdr);
+       u32 net_id = msg_bc_netid(hdr);
+       u32 mtyp = msg_type(hdr);
+       u32 signature = msg_node_sig(hdr);
+       u16 caps = msg_node_capabilities(hdr);
        bool respond = false;
+       bool dupl_addr = false;
 
-       bearer->media->msg2addr(bearer, &maddr, msg_media_addr(msg));
-       kfree_skb(buf);
+       bearer->media->msg2addr(bearer, &maddr, msg_media_addr(hdr));
+       kfree_skb(skb);
 
        /* Ensure message from node is valid and communication is permitted */
        if (net_id != tn->net_id)
@@ -164,91 +159,20 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf,
        if (!tipc_in_scope(bearer->domain, onode))
                return;
 
-       node = tipc_node_create(net, onode);
-       if (!node)
-               return;
-       tipc_node_lock(node);
-       node->capabilities = caps;
-
-       /* Prepare to validate requesting node's signature and media address */
-       sign_match = (signature == node->signature);
-       tipc_node_check_dest(node, bearer, &link_up, &addr_match, &maddr);
-
-       /* These three flags give us eight permutations: */
-
-       if (sign_match && addr_match && link_up) {
-               /* All is fine. Do nothing. */
-       } else if (sign_match && addr_match && !link_up) {
-               /* Respond. The link will come up in due time */
-               respond = true;
-       } else if (sign_match && !addr_match && link_up) {
-               /* Peer has changed i/f address without rebooting.
-                * If so, the link will reset soon, and the next
-                * discovery will be accepted. So we can ignore it.
-                * It may also be an cloned or malicious peer having
-                * chosen the same node address and signature as an
-                * existing one.
-                * Ignore requests until the link goes down, if ever.
-                */
+       tipc_node_check_dest(net, onode, bearer, caps, signature,
+                            &maddr, &respond, &dupl_addr);
+       if (dupl_addr)
                disc_dupl_alert(bearer, onode, &maddr);
-       } else if (sign_match && !addr_match && !link_up) {
-               /* Peer link has changed i/f address without rebooting.
-                * It may also be a cloned or malicious peer; we can't
-                * distinguish between the two.
-                * The signature is correct, so we must accept.
-                */
-               accept_addr = true;
-               respond = true;
-       } else if (!sign_match && addr_match && link_up) {
-               /* Peer node rebooted. Two possibilities:
-                *  - Delayed re-discovery; this link endpoint has already
-                *    reset and re-established contact with the peer, before
-                *    receiving a discovery message from that node.
-                *    (The peer happened to receive one from this node first).
-                *  - The peer came back so fast that our side has not
-                *    discovered it yet. Probing from this side will soon
-                *    reset the link, since there can be no working link
-                *    endpoint at the peer end, and the link will re-establish.
-                *  Accept the signature, since it comes from a known peer.
-                */
-               accept_sign = true;
-       } else if (!sign_match && addr_match && !link_up) {
-               /*  The peer node has rebooted.
-                *  Accept signature, since it is a known peer.
-                */
-               accept_sign = true;
-               respond = true;
-       } else if (!sign_match && !addr_match && link_up) {
-               /* Peer rebooted with new address, or a new/duplicate peer.
-                * Ignore until the link goes down, if ever.
-                */
-               disc_dupl_alert(bearer, onode, &maddr);
-       } else if (!sign_match && !addr_match && !link_up) {
-               /* Peer rebooted with new address, or it is a new peer.
-                * Accept signature and address.
-               */
-               accept_sign = true;
-               accept_addr = true;
-               respond = true;
-       }
-
-       if (accept_sign)
-               node->signature = signature;
-
-       if (accept_addr && !tipc_node_update_dest(node, bearer, &maddr))
-               respond = false;
 
        /* Send response, if necessary */
        if (respond && (mtyp == DSC_REQ_MSG)) {
-               rbuf = tipc_buf_acquire(MAX_H_SIZE);
-               if (rbuf) {
-                       tipc_disc_init_msg(net, rbuf, DSC_RESP_MSG, bearer);
-                       tipc_bearer_send(net, bearer->identity, rbuf, &maddr);
-                       kfree_skb(rbuf);
+               rskb = tipc_buf_acquire(MAX_H_SIZE);
+               if (rskb) {
+                       tipc_disc_init_msg(net, rskb, DSC_RESP_MSG, bearer);
+                       tipc_bearer_send(net, bearer->identity, rskb, &maddr);
+                       kfree_skb(rskb);
                }
        }
-       tipc_node_unlock(node);
-       tipc_node_put(node);
 }
 
 /**
index a3ceeda2a80a20a8dface69f98078c1979dc25a0..d03e88f2273b9b28a80cedf49483f3fae03a6efc 100644 (file)
@@ -138,7 +138,7 @@ struct tipc_node *tipc_node_find(struct net *net, u32 addr)
        return NULL;
 }
 
-struct tipc_node *tipc_node_create(struct net *net, u32 addr)
+struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities)
 {
        struct tipc_net *tn = net_generic(net, tipc_net_id);
        struct tipc_node *n_ptr, *temp_node;
@@ -154,6 +154,7 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr)
        }
        n_ptr->addr = addr;
        n_ptr->net = net;
+       n_ptr->capabilities = capabilities;
        kref_init(&n_ptr->kref);
        spin_lock_init(&n_ptr->lock);
        INIT_HLIST_NODE(&n_ptr->hash);
@@ -422,38 +423,118 @@ bool tipc_node_is_up(struct tipc_node *n)
        return n->active_links[0] != INVALID_BEARER_ID;
 }
 
-void tipc_node_check_dest(struct tipc_node *n, struct tipc_bearer *b,
-                         bool *link_up, bool *addr_match,
-                         struct tipc_media_addr *maddr)
+void tipc_node_check_dest(struct net *net, u32 onode,
+                         struct tipc_bearer *b,
+                         u16 capabilities, u32 signature,
+                         struct tipc_media_addr *maddr,
+                         bool *respond, bool *dupl_addr)
 {
-       struct tipc_link *l = n->links[b->identity].link;
-       struct tipc_media_addr *curr = &n->links[b->identity].maddr;
+       struct tipc_node *n;
+       struct tipc_link *l;
+       struct tipc_media_addr *curr_maddr;
+       struct sk_buff_head *inputq;
+       bool addr_match = false;
+       bool sign_match = false;
+       bool link_up = false;
+       bool accept_addr = false;
+
+       *dupl_addr = false;
+       *respond = false;
+
+       n = tipc_node_create(net, onode, capabilities);
+       if (!n)
+               return;
 
-       *link_up = l && tipc_link_is_up(l);
-       *addr_match = l && !memcmp(curr, maddr, sizeof(*maddr));
-}
+       tipc_node_lock(n);
 
-bool tipc_node_update_dest(struct tipc_node *n,  struct tipc_bearer *b,
-                          struct tipc_media_addr *maddr)
-{
-       struct tipc_link *l = n->links[b->identity].link;
-       struct tipc_media_addr *curr = &n->links[b->identity].maddr;
-       struct sk_buff_head *inputq = &n->links[b->identity].inputq;
+       curr_maddr = &n->links[b->identity].maddr;
+       inputq = &n->links[b->identity].inputq;
+
+       /* Prepare to validate requesting node's signature and media address */
+       l = n->links[b->identity].link;
+       link_up = l && tipc_link_is_up(l);
+       addr_match = l && !memcmp(curr_maddr, maddr, sizeof(*maddr));
+       sign_match = (signature == n->signature);
+
+       /* These three flags give us eight permutations: */
+
+       if (sign_match && addr_match && link_up) {
+               /* All is fine. Do nothing. */
+       } else if (sign_match && addr_match && !link_up) {
+               /* Respond. The link will come up in due time */
+               *respond = true;
+       } else if (sign_match && !addr_match && link_up) {
+               /* Peer has changed i/f address without rebooting.
+                * If so, the link will reset soon, and the next
+                * discovery will be accepted. So we can ignore it.
+                * It may also be an cloned or malicious peer having
+                * chosen the same node address and signature as an
+                * existing one.
+                * Ignore requests until the link goes down, if ever.
+                */
+               *dupl_addr = true;
+       } else if (sign_match && !addr_match && !link_up) {
+               /* Peer link has changed i/f address without rebooting.
+                * It may also be a cloned or malicious peer; we can't
+                * distinguish between the two.
+                * The signature is correct, so we must accept.
+                */
+               accept_addr = true;
+               *respond = true;
+       } else if (!sign_match && addr_match && link_up) {
+               /* Peer node rebooted. Two possibilities:
+                *  - Delayed re-discovery; this link endpoint has already
+                *    reset and re-established contact with the peer, before
+                *    receiving a discovery message from that node.
+                *    (The peer happened to receive one from this node first).
+                *  - The peer came back so fast that our side has not
+                *    discovered it yet. Probing from this side will soon
+                *    reset the link, since there can be no working link
+                *    endpoint at the peer end, and the link will re-establish.
+                *  Accept the signature, since it comes from a known peer.
+                */
+               n->signature = signature;
+       } else if (!sign_match && addr_match && !link_up) {
+               /*  The peer node has rebooted.
+                *  Accept signature, since it is a known peer.
+                */
+               n->signature = signature;
+               *respond = true;
+       } else if (!sign_match && !addr_match && link_up) {
+               /* Peer rebooted with new address, or a new/duplicate peer.
+                * Ignore until the link goes down, if ever.
+                */
+               *dupl_addr = true;
+       } else if (!sign_match && !addr_match && !link_up) {
+               /* Peer rebooted with new address, or it is a new peer.
+                * Accept signature and address.
+                */
+               n->signature = signature;
+               accept_addr = true;
+               *respond = true;
+       }
+
+       if (!accept_addr)
+               goto exit;
 
+       /* Now create new link if not already existing */
        if (!l) {
                l = tipc_link_create(n, b, maddr, inputq, &n->bclink.namedq);
-               if (!l)
-                       return false;
+               if (!l) {
+                       *respond = false;
+                       goto exit;
+               }
                tipc_node_calculate_timer(n, l);
-               if (n->link_cnt == 1) {
+               if (n->link_cnt == 1)
                        if (!mod_timer(&n->timer, jiffies + n->keepalive_intv))
                                tipc_node_get(n);
-               }
        }
        memcpy(&l->media_addr, maddr, sizeof(*maddr));
-       memcpy(curr, maddr, sizeof(*maddr));
+       memcpy(curr_maddr, maddr, sizeof(*maddr));
        tipc_node_link_down(n, b->identity);
-       return true;
+exit:
+       tipc_node_unlock(n);
+       tipc_node_put(n);
 }
 
 void tipc_node_delete_links(struct net *net, int bearer_id)
index 406c6fe0dbb2c5a8600cf759dd4f033030e23897..9a977467fc46a18995798afb8052aa6656eb860b 100644 (file)
@@ -147,13 +147,12 @@ struct tipc_node {
 
 struct tipc_node *tipc_node_find(struct net *net, u32 addr);
 void tipc_node_put(struct tipc_node *node);
-struct tipc_node *tipc_node_create(struct net *net, u32 addr);
 void tipc_node_stop(struct net *net);
-void tipc_node_check_dest(struct tipc_node *n, struct tipc_bearer *bearer,
-                         bool *link_up, bool *addr_match,
-                         struct tipc_media_addr *maddr);
-bool tipc_node_update_dest(struct tipc_node *n, struct tipc_bearer *bearer,
-                          struct tipc_media_addr *maddr);
+void tipc_node_check_dest(struct net *net, u32 onode,
+                         struct tipc_bearer *bearer,
+                         u16 capabilities, u32 signature,
+                         struct tipc_media_addr *maddr,
+                         bool *respond, bool *dupl_addr);
 void tipc_node_delete_links(struct net *net, int bearer_id);
 void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr);
 void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr);