diff options
Diffstat (limited to 'net/tipc/node.c')
| -rw-r--r-- | net/tipc/node.c | 85 |
1 files changed, 78 insertions, 7 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c index 7b0c99347406..4a95c8c155c6 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
| @@ -115,6 +115,7 @@ struct tipc_node { | |||
| 115 | u16 capabilities; | 115 | u16 capabilities; |
| 116 | u32 signature; | 116 | u32 signature; |
| 117 | u32 link_id; | 117 | u32 link_id; |
| 118 | u8 peer_id[16]; | ||
| 118 | struct list_head publ_list; | 119 | struct list_head publ_list; |
| 119 | struct list_head conn_sks; | 120 | struct list_head conn_sks; |
| 120 | unsigned long keepalive_intv; | 121 | unsigned long keepalive_intv; |
| @@ -156,6 +157,7 @@ static void tipc_node_delete(struct tipc_node *node); | |||
| 156 | static void tipc_node_timeout(struct timer_list *t); | 157 | static void tipc_node_timeout(struct timer_list *t); |
| 157 | static void tipc_node_fsm_evt(struct tipc_node *n, int evt); | 158 | static void tipc_node_fsm_evt(struct tipc_node *n, int evt); |
| 158 | static struct tipc_node *tipc_node_find(struct net *net, u32 addr); | 159 | static struct tipc_node *tipc_node_find(struct net *net, u32 addr); |
| 160 | static struct tipc_node *tipc_node_find_by_id(struct net *net, u8 *id); | ||
| 159 | static void tipc_node_put(struct tipc_node *node); | 161 | static void tipc_node_put(struct tipc_node *node); |
| 160 | static bool node_is_up(struct tipc_node *n); | 162 | static bool node_is_up(struct tipc_node *n); |
| 161 | 163 | ||
| @@ -245,6 +247,30 @@ static struct tipc_node *tipc_node_find(struct net *net, u32 addr) | |||
| 245 | return node; | 247 | return node; |
| 246 | } | 248 | } |
| 247 | 249 | ||
| 250 | /* tipc_node_find_by_id - locate specified node object by its 128-bit id | ||
| 251 | * Note: this function is called only when a discovery request failed | ||
| 252 | * to find the node by its 32-bit id, and is not time critical | ||
| 253 | */ | ||
| 254 | static struct tipc_node *tipc_node_find_by_id(struct net *net, u8 *id) | ||
| 255 | { | ||
| 256 | struct tipc_net *tn = tipc_net(net); | ||
| 257 | struct tipc_node *n; | ||
| 258 | bool found = false; | ||
| 259 | |||
| 260 | rcu_read_lock(); | ||
| 261 | list_for_each_entry_rcu(n, &tn->node_list, list) { | ||
| 262 | read_lock_bh(&n->lock); | ||
| 263 | if (!memcmp(id, n->peer_id, 16) && | ||
| 264 | kref_get_unless_zero(&n->kref)) | ||
| 265 | found = true; | ||
| 266 | read_unlock_bh(&n->lock); | ||
| 267 | if (found) | ||
| 268 | break; | ||
| 269 | } | ||
| 270 | rcu_read_unlock(); | ||
| 271 | return found ? n : NULL; | ||
| 272 | } | ||
| 273 | |||
| 248 | static void tipc_node_read_lock(struct tipc_node *n) | 274 | static void tipc_node_read_lock(struct tipc_node *n) |
| 249 | { | 275 | { |
| 250 | read_lock_bh(&n->lock); | 276 | read_lock_bh(&n->lock); |
| @@ -307,7 +333,8 @@ static void tipc_node_write_unlock(struct tipc_node *n) | |||
| 307 | } | 333 | } |
| 308 | } | 334 | } |
| 309 | 335 | ||
| 310 | struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) | 336 | struct tipc_node *tipc_node_create(struct net *net, u32 addr, |
| 337 | u8 *peer_id, u16 capabilities) | ||
| 311 | { | 338 | { |
| 312 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 339 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| 313 | struct tipc_node *n, *temp_node; | 340 | struct tipc_node *n, *temp_node; |
| @@ -326,6 +353,7 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) | |||
| 326 | goto exit; | 353 | goto exit; |
| 327 | } | 354 | } |
| 328 | n->addr = addr; | 355 | n->addr = addr; |
| 356 | memcpy(&n->peer_id, peer_id, 16); | ||
| 329 | n->net = net; | 357 | n->net = net; |
| 330 | n->capabilities = capabilities; | 358 | n->capabilities = capabilities; |
| 331 | kref_init(&n->kref); | 359 | kref_init(&n->kref); |
| @@ -344,8 +372,8 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) | |||
| 344 | n->signature = INVALID_NODE_SIG; | 372 | n->signature = INVALID_NODE_SIG; |
| 345 | n->active_links[0] = INVALID_BEARER_ID; | 373 | n->active_links[0] = INVALID_BEARER_ID; |
| 346 | n->active_links[1] = INVALID_BEARER_ID; | 374 | n->active_links[1] = INVALID_BEARER_ID; |
| 347 | if (!tipc_link_bc_create(net, tipc_own_addr(net), n->addr, | 375 | if (!tipc_link_bc_create(net, tipc_own_addr(net), |
| 348 | U16_MAX, | 376 | addr, U16_MAX, |
| 349 | tipc_link_window(tipc_bc_sndlink(net)), | 377 | tipc_link_window(tipc_bc_sndlink(net)), |
| 350 | n->capabilities, | 378 | n->capabilities, |
| 351 | &n->bc_entry.inputq1, | 379 | &n->bc_entry.inputq1, |
| @@ -735,8 +763,51 @@ bool tipc_node_is_up(struct net *net, u32 addr) | |||
| 735 | return retval; | 763 | return retval; |
| 736 | } | 764 | } |
| 737 | 765 | ||
| 738 | void tipc_node_check_dest(struct net *net, u32 onode, | 766 | static u32 tipc_node_suggest_addr(struct net *net, u32 addr) |
| 739 | struct tipc_bearer *b, | 767 | { |
| 768 | struct tipc_node *n; | ||
| 769 | |||
| 770 | addr ^= tipc_net(net)->random; | ||
| 771 | while ((n = tipc_node_find(net, addr))) { | ||
| 772 | tipc_node_put(n); | ||
| 773 | addr++; | ||
| 774 | } | ||
| 775 | return addr; | ||
| 776 | } | ||
| 777 | |||
| 778 | /* tipc_node_try_addr(): Check if addr can be used by peer, suggest other if not | ||
| 779 | */ | ||
| 780 | u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr) | ||
| 781 | { | ||
| 782 | struct tipc_net *tn = tipc_net(net); | ||
| 783 | struct tipc_node *n; | ||
| 784 | |||
| 785 | /* Suggest new address if some other peer is using this one */ | ||
| 786 | n = tipc_node_find(net, addr); | ||
| 787 | if (n) { | ||
| 788 | if (!memcmp(n->peer_id, id, NODE_ID_LEN)) | ||
| 789 | addr = 0; | ||
| 790 | tipc_node_put(n); | ||
| 791 | if (!addr) | ||
| 792 | return 0; | ||
| 793 | return tipc_node_suggest_addr(net, addr); | ||
| 794 | } | ||
| 795 | |||
| 796 | /* Suggest previously used address if peer is known */ | ||
| 797 | n = tipc_node_find_by_id(net, id); | ||
| 798 | if (n) { | ||
| 799 | addr = n->addr; | ||
| 800 | tipc_node_put(n); | ||
| 801 | } | ||
| 802 | /* Even this node may be in trial phase */ | ||
| 803 | if (tn->trial_addr == addr) | ||
| 804 | return tipc_node_suggest_addr(net, addr); | ||
| 805 | |||
| 806 | return addr; | ||
| 807 | } | ||
| 808 | |||
| 809 | void tipc_node_check_dest(struct net *net, u32 addr, | ||
| 810 | u8 *peer_id, struct tipc_bearer *b, | ||
| 740 | u16 capabilities, u32 signature, | 811 | u16 capabilities, u32 signature, |
| 741 | struct tipc_media_addr *maddr, | 812 | struct tipc_media_addr *maddr, |
| 742 | bool *respond, bool *dupl_addr) | 813 | bool *respond, bool *dupl_addr) |
| @@ -755,7 +826,7 @@ void tipc_node_check_dest(struct net *net, u32 onode, | |||
| 755 | *dupl_addr = false; | 826 | *dupl_addr = false; |
| 756 | *respond = false; | 827 | *respond = false; |
| 757 | 828 | ||
| 758 | n = tipc_node_create(net, onode, capabilities); | 829 | n = tipc_node_create(net, addr, peer_id, capabilities); |
| 759 | if (!n) | 830 | if (!n) |
| 760 | return; | 831 | return; |
| 761 | 832 | ||
| @@ -840,7 +911,7 @@ void tipc_node_check_dest(struct net *net, u32 onode, | |||
| 840 | if (!tipc_link_create(net, if_name, b->identity, b->tolerance, | 911 | if (!tipc_link_create(net, if_name, b->identity, b->tolerance, |
| 841 | b->net_plane, b->mtu, b->priority, | 912 | b->net_plane, b->mtu, b->priority, |
| 842 | b->window, mod(tipc_net(net)->random), | 913 | b->window, mod(tipc_net(net)->random), |
| 843 | tipc_own_addr(net), onode, | 914 | tipc_own_addr(net), addr, peer_id, |
| 844 | n->capabilities, | 915 | n->capabilities, |
| 845 | tipc_bc_sndlink(n->net), n->bc_entry.link, | 916 | tipc_bc_sndlink(n->net), n->bc_entry.link, |
| 846 | &le->inputq, | 917 | &le->inputq, |
