Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jon Paul Maloy and committed by
David S. Miller
cf148816 662921cd

+127 -123
+20 -96
net/tipc/discover.c
··· 120 120 * @buf: buffer containing message 121 121 * @bearer: bearer that message arrived on 122 122 */ 123 - void tipc_disc_rcv(struct net *net, struct sk_buff *buf, 123 + void tipc_disc_rcv(struct net *net, struct sk_buff *skb, 124 124 struct tipc_bearer *bearer) 125 125 { 126 126 struct tipc_net *tn = net_generic(net, tipc_net_id); 127 - struct tipc_node *node; 128 127 struct tipc_media_addr maddr; 129 - struct sk_buff *rbuf; 130 - struct tipc_msg *msg = buf_msg(buf); 131 - u32 ddom = msg_dest_domain(msg); 132 - u32 onode = msg_prevnode(msg); 133 - u32 net_id = msg_bc_netid(msg); 134 - u32 mtyp = msg_type(msg); 135 - u32 signature = msg_node_sig(msg); 136 - u16 caps = msg_node_capabilities(msg); 137 - bool addr_match = false; 138 - bool sign_match = false; 139 - bool link_up = false; 140 - bool accept_addr = false; 141 - bool accept_sign = false; 128 + struct sk_buff *rskb; 129 + struct tipc_msg *hdr = buf_msg(skb); 130 + u32 ddom = msg_dest_domain(hdr); 131 + u32 onode = msg_prevnode(hdr); 132 + u32 net_id = msg_bc_netid(hdr); 133 + u32 mtyp = msg_type(hdr); 134 + u32 signature = msg_node_sig(hdr); 135 + u16 caps = msg_node_capabilities(hdr); 142 136 bool respond = false; 137 + bool dupl_addr = false; 143 138 144 - bearer->media->msg2addr(bearer, &maddr, msg_media_addr(msg)); 145 - kfree_skb(buf); 139 + bearer->media->msg2addr(bearer, &maddr, msg_media_addr(hdr)); 140 + kfree_skb(skb); 146 141 147 142 /* Ensure message from node is valid and communication is permitted */ 148 143 if (net_id != tn->net_id) ··· 159 164 if (!tipc_in_scope(bearer->domain, onode)) 160 165 return; 161 166 162 - node = tipc_node_create(net, onode); 163 - if (!node) 164 - return; 165 - tipc_node_lock(node); 166 - node->capabilities = caps; 167 - 168 - /* Prepare to validate requesting node's signature and media address */ 169 - sign_match = (signature == node->signature); 170 - tipc_node_check_dest(node, bearer, &link_up, &addr_match, &maddr); 171 - 172 - /* These three flags give us eight permutations: */ 173 - 174 - if (sign_match && addr_match && link_up) { 175 - /* All is fine. Do nothing. */ 176 - } else if (sign_match && addr_match && !link_up) { 177 - /* Respond. The link will come up in due time */ 178 - respond = true; 179 - } else if (sign_match && !addr_match && link_up) { 180 - /* Peer has changed i/f address without rebooting. 181 - * If so, the link will reset soon, and the next 182 - * discovery will be accepted. So we can ignore it. 183 - * It may also be an cloned or malicious peer having 184 - * chosen the same node address and signature as an 185 - * existing one. 186 - * Ignore requests until the link goes down, if ever. 187 - */ 167 + tipc_node_check_dest(net, onode, bearer, caps, signature, 168 + &maddr, &respond, &dupl_addr); 169 + if (dupl_addr) 188 170 disc_dupl_alert(bearer, onode, &maddr); 189 - } else if (sign_match && !addr_match && !link_up) { 190 - /* Peer link has changed i/f address without rebooting. 191 - * It may also be a cloned or malicious peer; we can't 192 - * distinguish between the two. 193 - * The signature is correct, so we must accept. 194 - */ 195 - accept_addr = true; 196 - respond = true; 197 - } else if (!sign_match && addr_match && link_up) { 198 - /* Peer node rebooted. Two possibilities: 199 - * - Delayed re-discovery; this link endpoint has already 200 - * reset and re-established contact with the peer, before 201 - * receiving a discovery message from that node. 202 - * (The peer happened to receive one from this node first). 203 - * - The peer came back so fast that our side has not 204 - * discovered it yet. Probing from this side will soon 205 - * reset the link, since there can be no working link 206 - * endpoint at the peer end, and the link will re-establish. 207 - * Accept the signature, since it comes from a known peer. 208 - */ 209 - accept_sign = true; 210 - } else if (!sign_match && addr_match && !link_up) { 211 - /* The peer node has rebooted. 212 - * Accept signature, since it is a known peer. 213 - */ 214 - accept_sign = true; 215 - respond = true; 216 - } else if (!sign_match && !addr_match && link_up) { 217 - /* Peer rebooted with new address, or a new/duplicate peer. 218 - * Ignore until the link goes down, if ever. 219 - */ 220 - disc_dupl_alert(bearer, onode, &maddr); 221 - } else if (!sign_match && !addr_match && !link_up) { 222 - /* Peer rebooted with new address, or it is a new peer. 223 - * Accept signature and address. 224 - */ 225 - accept_sign = true; 226 - accept_addr = true; 227 - respond = true; 228 - } 229 - 230 - if (accept_sign) 231 - node->signature = signature; 232 - 233 - if (accept_addr && !tipc_node_update_dest(node, bearer, &maddr)) 234 - respond = false; 235 171 236 172 /* Send response, if necessary */ 237 173 if (respond && (mtyp == DSC_REQ_MSG)) { 238 - rbuf = tipc_buf_acquire(MAX_H_SIZE); 239 - if (rbuf) { 240 - tipc_disc_init_msg(net, rbuf, DSC_RESP_MSG, bearer); 241 - tipc_bearer_send(net, bearer->identity, rbuf, &maddr); 242 - kfree_skb(rbuf); 174 + rskb = tipc_buf_acquire(MAX_H_SIZE); 175 + if (rskb) { 176 + tipc_disc_init_msg(net, rskb, DSC_RESP_MSG, bearer); 177 + tipc_bearer_send(net, bearer->identity, rskb, &maddr); 178 + kfree_skb(rskb); 243 179 } 244 180 } 245 - tipc_node_unlock(node); 246 - tipc_node_put(node); 247 181 } 248 182 249 183 /**
+102 -21
net/tipc/node.c
··· 138 138 return NULL; 139 139 } 140 140 141 - struct tipc_node *tipc_node_create(struct net *net, u32 addr) 141 + struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) 142 142 { 143 143 struct tipc_net *tn = net_generic(net, tipc_net_id); 144 144 struct tipc_node *n_ptr, *temp_node; ··· 154 154 } 155 155 n_ptr->addr = addr; 156 156 n_ptr->net = net; 157 + n_ptr->capabilities = capabilities; 157 158 kref_init(&n_ptr->kref); 158 159 spin_lock_init(&n_ptr->lock); 159 160 INIT_HLIST_NODE(&n_ptr->hash); ··· 423 422 return n->active_links[0] != INVALID_BEARER_ID; 424 423 } 425 424 426 - void tipc_node_check_dest(struct tipc_node *n, struct tipc_bearer *b, 427 - bool *link_up, bool *addr_match, 428 - struct tipc_media_addr *maddr) 425 + void tipc_node_check_dest(struct net *net, u32 onode, 426 + struct tipc_bearer *b, 427 + u16 capabilities, u32 signature, 428 + struct tipc_media_addr *maddr, 429 + bool *respond, bool *dupl_addr) 429 430 { 430 - struct tipc_link *l = n->links[b->identity].link; 431 - struct tipc_media_addr *curr = &n->links[b->identity].maddr; 431 + struct tipc_node *n; 432 + struct tipc_link *l; 433 + struct tipc_media_addr *curr_maddr; 434 + struct sk_buff_head *inputq; 435 + bool addr_match = false; 436 + bool sign_match = false; 437 + bool link_up = false; 438 + bool accept_addr = false; 432 439 433 - *link_up = l && tipc_link_is_up(l); 434 - *addr_match = l && !memcmp(curr, maddr, sizeof(*maddr)); 435 - } 440 + *dupl_addr = false; 441 + *respond = false; 436 442 437 - bool tipc_node_update_dest(struct tipc_node *n, struct tipc_bearer *b, 438 - struct tipc_media_addr *maddr) 439 - { 440 - struct tipc_link *l = n->links[b->identity].link; 441 - struct tipc_media_addr *curr = &n->links[b->identity].maddr; 442 - struct sk_buff_head *inputq = &n->links[b->identity].inputq; 443 + n = tipc_node_create(net, onode, capabilities); 444 + if (!n) 445 + return; 443 446 447 + tipc_node_lock(n); 448 + 449 + curr_maddr = &n->links[b->identity].maddr; 450 + inputq = &n->links[b->identity].inputq; 451 + 452 + /* Prepare to validate requesting node's signature and media address */ 453 + l = n->links[b->identity].link; 454 + link_up = l && tipc_link_is_up(l); 455 + addr_match = l && !memcmp(curr_maddr, maddr, sizeof(*maddr)); 456 + sign_match = (signature == n->signature); 457 + 458 + /* These three flags give us eight permutations: */ 459 + 460 + if (sign_match && addr_match && link_up) { 461 + /* All is fine. Do nothing. */ 462 + } else if (sign_match && addr_match && !link_up) { 463 + /* Respond. The link will come up in due time */ 464 + *respond = true; 465 + } else if (sign_match && !addr_match && link_up) { 466 + /* Peer has changed i/f address without rebooting. 467 + * If so, the link will reset soon, and the next 468 + * discovery will be accepted. So we can ignore it. 469 + * It may also be an cloned or malicious peer having 470 + * chosen the same node address and signature as an 471 + * existing one. 472 + * Ignore requests until the link goes down, if ever. 473 + */ 474 + *dupl_addr = true; 475 + } else if (sign_match && !addr_match && !link_up) { 476 + /* Peer link has changed i/f address without rebooting. 477 + * It may also be a cloned or malicious peer; we can't 478 + * distinguish between the two. 479 + * The signature is correct, so we must accept. 480 + */ 481 + accept_addr = true; 482 + *respond = true; 483 + } else if (!sign_match && addr_match && link_up) { 484 + /* Peer node rebooted. Two possibilities: 485 + * - Delayed re-discovery; this link endpoint has already 486 + * reset and re-established contact with the peer, before 487 + * receiving a discovery message from that node. 488 + * (The peer happened to receive one from this node first). 489 + * - The peer came back so fast that our side has not 490 + * discovered it yet. Probing from this side will soon 491 + * reset the link, since there can be no working link 492 + * endpoint at the peer end, and the link will re-establish. 493 + * Accept the signature, since it comes from a known peer. 494 + */ 495 + n->signature = signature; 496 + } else if (!sign_match && addr_match && !link_up) { 497 + /* The peer node has rebooted. 498 + * Accept signature, since it is a known peer. 499 + */ 500 + n->signature = signature; 501 + *respond = true; 502 + } else if (!sign_match && !addr_match && link_up) { 503 + /* Peer rebooted with new address, or a new/duplicate peer. 504 + * Ignore until the link goes down, if ever. 505 + */ 506 + *dupl_addr = true; 507 + } else if (!sign_match && !addr_match && !link_up) { 508 + /* Peer rebooted with new address, or it is a new peer. 509 + * Accept signature and address. 510 + */ 511 + n->signature = signature; 512 + accept_addr = true; 513 + *respond = true; 514 + } 515 + 516 + if (!accept_addr) 517 + goto exit; 518 + 519 + /* Now create new link if not already existing */ 444 520 if (!l) { 445 521 l = tipc_link_create(n, b, maddr, inputq, &n->bclink.namedq); 446 - if (!l) 447 - return false; 522 + if (!l) { 523 + *respond = false; 524 + goto exit; 525 + } 448 526 tipc_node_calculate_timer(n, l); 449 - if (n->link_cnt == 1) { 527 + if (n->link_cnt == 1) 450 528 if (!mod_timer(&n->timer, jiffies + n->keepalive_intv)) 451 529 tipc_node_get(n); 452 - } 453 530 } 454 531 memcpy(&l->media_addr, maddr, sizeof(*maddr)); 455 - memcpy(curr, maddr, sizeof(*maddr)); 532 + memcpy(curr_maddr, maddr, sizeof(*maddr)); 456 533 tipc_node_link_down(n, b->identity); 457 - return true; 534 + exit: 535 + tipc_node_unlock(n); 536 + tipc_node_put(n); 458 537 } 459 538 460 539 void tipc_node_delete_links(struct net *net, int bearer_id)
+5 -6
net/tipc/node.h
··· 147 147 148 148 struct tipc_node *tipc_node_find(struct net *net, u32 addr); 149 149 void tipc_node_put(struct tipc_node *node); 150 - struct tipc_node *tipc_node_create(struct net *net, u32 addr); 151 150 void tipc_node_stop(struct net *net); 152 - void tipc_node_check_dest(struct tipc_node *n, struct tipc_bearer *bearer, 153 - bool *link_up, bool *addr_match, 154 - struct tipc_media_addr *maddr); 155 - bool tipc_node_update_dest(struct tipc_node *n, struct tipc_bearer *bearer, 156 - struct tipc_media_addr *maddr); 151 + void tipc_node_check_dest(struct net *net, u32 onode, 152 + struct tipc_bearer *bearer, 153 + u16 capabilities, u32 signature, 154 + struct tipc_media_addr *maddr, 155 + bool *respond, bool *dupl_addr); 157 156 void tipc_node_delete_links(struct net *net, int bearer_id); 158 157 void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); 159 158 void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr);