tipc: move received discovery data evaluation inside node.c
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>
This commit is contained in:
Родитель
662921cd0a
Коммит
cf148816ac
|
@ -120,29 +120,24 @@ static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr,
|
||||||
* @buf: buffer containing message
|
* @buf: buffer containing message
|
||||||
* @bearer: bearer that message arrived on
|
* @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_bearer *bearer)
|
||||||
{
|
{
|
||||||
struct tipc_net *tn = net_generic(net, tipc_net_id);
|
struct tipc_net *tn = net_generic(net, tipc_net_id);
|
||||||
struct tipc_node *node;
|
|
||||||
struct tipc_media_addr maddr;
|
struct tipc_media_addr maddr;
|
||||||
struct sk_buff *rbuf;
|
struct sk_buff *rskb;
|
||||||
struct tipc_msg *msg = buf_msg(buf);
|
struct tipc_msg *hdr = buf_msg(skb);
|
||||||
u32 ddom = msg_dest_domain(msg);
|
u32 ddom = msg_dest_domain(hdr);
|
||||||
u32 onode = msg_prevnode(msg);
|
u32 onode = msg_prevnode(hdr);
|
||||||
u32 net_id = msg_bc_netid(msg);
|
u32 net_id = msg_bc_netid(hdr);
|
||||||
u32 mtyp = msg_type(msg);
|
u32 mtyp = msg_type(hdr);
|
||||||
u32 signature = msg_node_sig(msg);
|
u32 signature = msg_node_sig(hdr);
|
||||||
u16 caps = msg_node_capabilities(msg);
|
u16 caps = msg_node_capabilities(hdr);
|
||||||
bool addr_match = false;
|
|
||||||
bool sign_match = false;
|
|
||||||
bool link_up = false;
|
|
||||||
bool accept_addr = false;
|
|
||||||
bool accept_sign = false;
|
|
||||||
bool respond = false;
|
bool respond = false;
|
||||||
|
bool dupl_addr = false;
|
||||||
|
|
||||||
bearer->media->msg2addr(bearer, &maddr, msg_media_addr(msg));
|
bearer->media->msg2addr(bearer, &maddr, msg_media_addr(hdr));
|
||||||
kfree_skb(buf);
|
kfree_skb(skb);
|
||||||
|
|
||||||
/* Ensure message from node is valid and communication is permitted */
|
/* Ensure message from node is valid and communication is permitted */
|
||||||
if (net_id != tn->net_id)
|
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))
|
if (!tipc_in_scope(bearer->domain, onode))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
node = tipc_node_create(net, onode);
|
tipc_node_check_dest(net, onode, bearer, caps, signature,
|
||||||
if (!node)
|
&maddr, &respond, &dupl_addr);
|
||||||
return;
|
if (dupl_addr)
|
||||||
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.
|
|
||||||
*/
|
|
||||||
disc_dupl_alert(bearer, onode, &maddr);
|
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 */
|
/* Send response, if necessary */
|
||||||
if (respond && (mtyp == DSC_REQ_MSG)) {
|
if (respond && (mtyp == DSC_REQ_MSG)) {
|
||||||
rbuf = tipc_buf_acquire(MAX_H_SIZE);
|
rskb = tipc_buf_acquire(MAX_H_SIZE);
|
||||||
if (rbuf) {
|
if (rskb) {
|
||||||
tipc_disc_init_msg(net, rbuf, DSC_RESP_MSG, bearer);
|
tipc_disc_init_msg(net, rskb, DSC_RESP_MSG, bearer);
|
||||||
tipc_bearer_send(net, bearer->identity, rbuf, &maddr);
|
tipc_bearer_send(net, bearer->identity, rskb, &maddr);
|
||||||
kfree_skb(rbuf);
|
kfree_skb(rskb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tipc_node_unlock(node);
|
|
||||||
tipc_node_put(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
123
net/tipc/node.c
123
net/tipc/node.c
|
@ -138,7 +138,7 @@ struct tipc_node *tipc_node_find(struct net *net, u32 addr)
|
||||||
return NULL;
|
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_net *tn = net_generic(net, tipc_net_id);
|
||||||
struct tipc_node *n_ptr, *temp_node;
|
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->addr = addr;
|
||||||
n_ptr->net = net;
|
n_ptr->net = net;
|
||||||
|
n_ptr->capabilities = capabilities;
|
||||||
kref_init(&n_ptr->kref);
|
kref_init(&n_ptr->kref);
|
||||||
spin_lock_init(&n_ptr->lock);
|
spin_lock_init(&n_ptr->lock);
|
||||||
INIT_HLIST_NODE(&n_ptr->hash);
|
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;
|
return n->active_links[0] != INVALID_BEARER_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tipc_node_check_dest(struct tipc_node *n, struct tipc_bearer *b,
|
void tipc_node_check_dest(struct net *net, u32 onode,
|
||||||
bool *link_up, bool *addr_match,
|
struct tipc_bearer *b,
|
||||||
struct tipc_media_addr *maddr)
|
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_node *n;
|
||||||
struct tipc_media_addr *curr = &n->links[b->identity].maddr;
|
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;
|
||||||
|
|
||||||
*link_up = l && tipc_link_is_up(l);
|
*dupl_addr = false;
|
||||||
*addr_match = l && !memcmp(curr, maddr, sizeof(*maddr));
|
*respond = false;
|
||||||
}
|
|
||||||
|
|
||||||
bool tipc_node_update_dest(struct tipc_node *n, struct tipc_bearer *b,
|
n = tipc_node_create(net, onode, capabilities);
|
||||||
struct tipc_media_addr *maddr)
|
if (!n)
|
||||||
{
|
return;
|
||||||
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;
|
|
||||||
|
|
||||||
|
tipc_node_lock(n);
|
||||||
|
|
||||||
|
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) {
|
if (!l) {
|
||||||
l = tipc_link_create(n, b, maddr, inputq, &n->bclink.namedq);
|
l = tipc_link_create(n, b, maddr, inputq, &n->bclink.namedq);
|
||||||
if (!l)
|
if (!l) {
|
||||||
return false;
|
*respond = false;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
tipc_node_calculate_timer(n, l);
|
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))
|
if (!mod_timer(&n->timer, jiffies + n->keepalive_intv))
|
||||||
tipc_node_get(n);
|
tipc_node_get(n);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
memcpy(&l->media_addr, maddr, sizeof(*maddr));
|
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);
|
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)
|
void tipc_node_delete_links(struct net *net, int bearer_id)
|
||||||
|
|
|
@ -147,13 +147,12 @@ struct tipc_node {
|
||||||
|
|
||||||
struct tipc_node *tipc_node_find(struct net *net, u32 addr);
|
struct tipc_node *tipc_node_find(struct net *net, u32 addr);
|
||||||
void tipc_node_put(struct tipc_node *node);
|
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_stop(struct net *net);
|
||||||
void tipc_node_check_dest(struct tipc_node *n, struct tipc_bearer *bearer,
|
void tipc_node_check_dest(struct net *net, u32 onode,
|
||||||
bool *link_up, bool *addr_match,
|
struct tipc_bearer *bearer,
|
||||||
struct tipc_media_addr *maddr);
|
u16 capabilities, u32 signature,
|
||||||
bool tipc_node_update_dest(struct tipc_node *n, struct tipc_bearer *bearer,
|
struct tipc_media_addr *maddr,
|
||||||
struct tipc_media_addr *maddr);
|
bool *respond, bool *dupl_addr);
|
||||||
void tipc_node_delete_links(struct net *net, int bearer_id);
|
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_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);
|
void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче