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, |