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

tipc: handle collisions of 32-bit node address hash values

When a 32-bit node address is generated from a 128-bit identifier,
there is a risk of collisions which must be discovered and handled.

We do this as follows:
- We don't apply the generated address immediately to the node, but do
instead initiate a 1 sec trial period to allow other cluster members
to discover and handle such collisions.

- During the trial period the node periodically sends out a new type
of message, DSC_TRIAL_MSG, using broadcast or emulated broadcast,
to all the other nodes in the cluster.

- When a node is receiving such a message, it must check that the
presented 32-bit identifier either is unused, or was used by the very
same peer in a previous session. In both cases it accepts the request
by not responding to it.

- If it finds that the same node has been up before using a different
address, it responds with a DSC_TRIAL_FAIL_MSG containing that
address.

- If it finds that the address has already been taken by some other
node, it generates a new, unused address and returns it to the
requester.

- During the trial period the requesting node must always be prepared
to accept a failure message, i.e., a message where a peer suggests a
different (or equal) address to the one tried. In those cases it
must apply the suggested value as trial address and restart the trial
period.

This algorithm ensures that in the vast majority of cases a node will
have the same address before and after a reboot. If a legacy user
configures the address explicitly, there will be no trial period and
messages, so this protocol addition is completely backwards compatible.

Acked-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 Maloy and committed by
David S. Miller
25b0b9c4 d50ccc2d

+236 -45
+2 -1
net/tipc/addr.c
··· 59 59 60 60 memcpy(tn->node_id, id, NODE_ID_LEN); 61 61 tipc_nodeid2string(tn->node_id_string, id); 62 - tn->node_addr = tmp[0] ^ tmp[1] ^ tmp[2] ^ tmp[3]; 62 + tn->trial_addr = tmp[0] ^ tmp[1] ^ tmp[2] ^ tmp[3]; 63 63 pr_info("Own node identity %s, cluster identity %u\n", 64 64 tipc_own_id_string(net), tn->net_id); 65 65 } ··· 74 74 sprintf(node_id, "%x", addr); 75 75 tipc_set_node_id(net, node_id); 76 76 } 77 + tn->trial_addr = addr; 77 78 pr_info("32-bit node address hash set to %x\n", addr); 78 79 } 79 80
+1 -2
net/tipc/bearer.c
··· 235 235 { 236 236 struct tipc_net *tn = tipc_net(net); 237 237 struct tipc_bearer_names b_names; 238 - u32 self = tipc_own_addr(net); 239 238 int with_this_prio = 1; 240 239 struct tipc_bearer *b; 241 240 struct tipc_media *m; ··· 243 244 int res = -EINVAL; 244 245 char *errstr = ""; 245 246 246 - if (!self) { 247 + if (!tipc_own_id(net)) { 247 248 errstr = "not supported in standalone mode"; 248 249 res = -ENOPROTOOPT; 249 250 goto rejected;
+2
net/tipc/core.c
··· 57 57 58 58 tn->net_id = 4711; 59 59 tn->node_addr = 0; 60 + tn->trial_addr = 0; 61 + tn->addr_trial_end = 0; 60 62 memset(tn->node_id, 0, sizeof(tn->node_id)); 61 63 memset(tn->node_id_string, 0, sizeof(tn->node_id_string)); 62 64 tn->mon_threshold = TIPC_DEF_MON_THRESHOLD;
+2
net/tipc/core.h
··· 82 82 struct tipc_net { 83 83 u8 node_id[NODE_ID_LEN]; 84 84 u32 node_addr; 85 + u32 trial_addr; 86 + unsigned long addr_trial_end; 85 87 char node_id_string[NODE_ID_STR_LEN]; 86 88 int net_id; 87 89 int random;
+107 -19
net/tipc/discover.c
··· 1 1 /* 2 2 * net/tipc/discover.c 3 3 * 4 - * Copyright (c) 2003-2006, 2014-2015, Ericsson AB 4 + * Copyright (c) 2003-2006, 2014-2018, Ericsson AB 5 5 * Copyright (c) 2005-2006, 2010-2011, Wind River Systems 6 6 * All rights reserved. 7 7 * ··· 78 78 * @b: ptr to bearer issuing message 79 79 */ 80 80 static void tipc_disc_init_msg(struct net *net, struct sk_buff *skb, 81 - u32 mtyp, struct tipc_bearer *b) 81 + u32 mtyp, struct tipc_bearer *b) 82 82 { 83 83 struct tipc_net *tn = tipc_net(net); 84 - u32 self = tipc_own_addr(net); 85 84 u32 dest_domain = b->domain; 86 85 struct tipc_msg *hdr; 87 86 88 87 hdr = buf_msg(skb); 89 - tipc_msg_init(self, hdr, LINK_CONFIG, mtyp, 88 + tipc_msg_init(tn->trial_addr, hdr, LINK_CONFIG, mtyp, 90 89 MAX_H_SIZE, dest_domain); 90 + msg_set_size(hdr, MAX_H_SIZE + NODE_ID_LEN); 91 91 msg_set_non_seq(hdr, 1); 92 92 msg_set_node_sig(hdr, tn->random); 93 93 msg_set_node_capabilities(hdr, TIPC_NODE_CAPABILITIES); 94 94 msg_set_dest_domain(hdr, dest_domain); 95 95 msg_set_bc_netid(hdr, tn->net_id); 96 96 b->media->addr2msg(msg_media_addr(hdr), &b->addr); 97 + msg_set_node_id(hdr, tipc_own_id(net)); 97 98 } 98 99 99 - static void tipc_disc_msg_xmit(struct net *net, u32 mtyp, u32 dst, u32 src, 100 + static void tipc_disc_msg_xmit(struct net *net, u32 mtyp, u32 dst, 101 + u32 src, u32 sugg_addr, 100 102 struct tipc_media_addr *maddr, 101 103 struct tipc_bearer *b) 102 104 { 105 + struct tipc_msg *hdr; 103 106 struct sk_buff *skb; 104 107 105 - skb = tipc_buf_acquire(MAX_H_SIZE, GFP_ATOMIC); 108 + skb = tipc_buf_acquire(MAX_H_SIZE + NODE_ID_LEN, GFP_ATOMIC); 106 109 if (!skb) 107 110 return; 111 + hdr = buf_msg(skb); 108 112 tipc_disc_init_msg(net, skb, mtyp, b); 113 + msg_set_sugg_node_addr(hdr, sugg_addr); 114 + msg_set_dest_domain(hdr, dst); 109 115 tipc_bearer_xmit_skb(net, b->identity, skb, maddr); 110 116 } 111 117 ··· 132 126 media_addr_str, b->name); 133 127 } 134 128 129 + /* tipc_disc_addr_trial(): - handle an address uniqueness trial from peer 130 + */ 131 + bool tipc_disc_addr_trial_msg(struct tipc_discoverer *d, 132 + struct tipc_media_addr *maddr, 133 + struct tipc_bearer *b, 134 + u32 dst, u32 src, 135 + u32 sugg_addr, 136 + u8 *peer_id, 137 + int mtyp) 138 + { 139 + struct net *net = d->net; 140 + struct tipc_net *tn = tipc_net(net); 141 + bool trial = time_before(jiffies, tn->addr_trial_end); 142 + u32 self = tipc_own_addr(net); 143 + 144 + if (mtyp == DSC_TRIAL_FAIL_MSG) { 145 + if (!trial) 146 + return true; 147 + 148 + /* Ignore if somebody else already gave new suggestion */ 149 + if (dst != tn->trial_addr) 150 + return true; 151 + 152 + /* Otherwise update trial address and restart trial period */ 153 + tn->trial_addr = sugg_addr; 154 + msg_set_prevnode(buf_msg(d->skb), sugg_addr); 155 + tn->addr_trial_end = jiffies + msecs_to_jiffies(1000); 156 + return true; 157 + } 158 + 159 + /* Apply trial address if we just left trial period */ 160 + if (!trial && !self) { 161 + tipc_net_finalize(net, tn->trial_addr); 162 + msg_set_type(buf_msg(d->skb), DSC_REQ_MSG); 163 + } 164 + 165 + if (mtyp != DSC_TRIAL_MSG) 166 + return false; 167 + 168 + sugg_addr = tipc_node_try_addr(net, peer_id, src); 169 + if (sugg_addr) 170 + tipc_disc_msg_xmit(net, DSC_TRIAL_FAIL_MSG, src, 171 + self, sugg_addr, maddr, b); 172 + return true; 173 + } 174 + 135 175 /** 136 176 * tipc_disc_rcv - handle incoming discovery message (request or response) 137 177 * @net: applicable net namespace ··· 191 139 struct tipc_msg *hdr = buf_msg(skb); 192 140 u16 caps = msg_node_capabilities(hdr); 193 141 bool legacy = tn->legacy_addr_format; 142 + u32 sugg = msg_sugg_node_addr(hdr); 194 143 u32 signature = msg_node_sig(hdr); 144 + u8 peer_id[NODE_ID_LEN] = {0,}; 195 145 u32 dst = msg_dest_domain(hdr); 196 146 u32 net_id = msg_bc_netid(hdr); 197 - u32 self = tipc_own_addr(net); 198 147 struct tipc_media_addr maddr; 199 148 u32 src = msg_prevnode(hdr); 200 149 u32 mtyp = msg_type(hdr); 201 150 bool dupl_addr = false; 202 151 bool respond = false; 152 + u32 self; 203 153 int err; 154 + 155 + skb_linearize(skb); 156 + hdr = buf_msg(skb); 157 + 158 + if (caps & TIPC_NODE_ID128) 159 + memcpy(peer_id, msg_node_id(hdr), NODE_ID_LEN); 160 + else 161 + sprintf(peer_id, "%x", src); 204 162 205 163 err = b->media->msg2addr(b, &maddr, msg_media_addr(hdr)); 206 164 kfree_skb(skb); ··· 223 161 return; 224 162 if (net_id != tn->net_id) 225 163 return; 164 + if (tipc_disc_addr_trial_msg(b->disc, &maddr, b, dst, 165 + src, sugg, peer_id, mtyp)) 166 + return; 167 + self = tipc_own_addr(net); 168 + 169 + /* Message from somebody using this node's address */ 226 170 if (in_own_node(net, src)) { 227 171 disc_dupl_alert(b, self, &maddr); 228 172 return; ··· 237 169 return; 238 170 if (!tipc_in_scope(legacy, b->domain, src)) 239 171 return; 240 - 241 - tipc_node_check_dest(net, src, b, caps, signature, 172 + tipc_node_check_dest(net, src, peer_id, b, caps, signature, 242 173 &maddr, &respond, &dupl_addr); 243 174 if (dupl_addr) 244 175 disc_dupl_alert(b, src, &maddr); ··· 245 178 return; 246 179 if (mtyp != DSC_REQ_MSG) 247 180 return; 248 - tipc_disc_msg_xmit(net, DSC_RESP_MSG, src, self, &maddr, b); 181 + tipc_disc_msg_xmit(net, DSC_RESP_MSG, src, self, 0, &maddr, b); 249 182 } 250 183 251 184 /* tipc_disc_add_dest - increment set of discovered nodes ··· 283 216 static void tipc_disc_timeout(struct timer_list *t) 284 217 { 285 218 struct tipc_discoverer *d = from_timer(d, t, timer); 219 + struct tipc_net *tn = tipc_net(d->net); 220 + u32 self = tipc_own_addr(d->net); 286 221 struct tipc_media_addr maddr; 287 222 struct sk_buff *skb = NULL; 288 - struct net *net; 223 + struct net *net = d->net; 289 224 u32 bearer_id; 290 225 291 226 spin_lock_bh(&d->lock); ··· 297 228 d->timer_intv = TIPC_DISC_INACTIVE; 298 229 goto exit; 299 230 } 231 + 232 + /* Did we just leave the address trial period ? */ 233 + if (!self && !time_before(jiffies, tn->addr_trial_end)) { 234 + self = tn->trial_addr; 235 + tipc_net_finalize(net, self); 236 + msg_set_prevnode(buf_msg(d->skb), self); 237 + msg_set_type(buf_msg(d->skb), DSC_REQ_MSG); 238 + } 239 + 300 240 /* Adjust timeout interval according to discovery phase */ 301 - d->timer_intv *= 2; 302 - if (d->num_nodes && d->timer_intv > TIPC_DISC_SLOW) 303 - d->timer_intv = TIPC_DISC_SLOW; 304 - else if (!d->num_nodes && d->timer_intv > TIPC_DISC_FAST) 305 - d->timer_intv = TIPC_DISC_FAST; 241 + if (time_before(jiffies, tn->addr_trial_end)) { 242 + d->timer_intv = TIPC_DISC_INIT; 243 + } else { 244 + d->timer_intv *= 2; 245 + if (d->num_nodes && d->timer_intv > TIPC_DISC_SLOW) 246 + d->timer_intv = TIPC_DISC_SLOW; 247 + else if (!d->num_nodes && d->timer_intv > TIPC_DISC_FAST) 248 + d->timer_intv = TIPC_DISC_FAST; 249 + } 250 + 306 251 mod_timer(&d->timer, jiffies + d->timer_intv); 307 252 memcpy(&maddr, &d->dest, sizeof(maddr)); 308 253 skb = skb_clone(d->skb, GFP_ATOMIC); 309 - net = d->net; 310 254 bearer_id = d->bearer_id; 311 255 exit: 312 256 spin_unlock_bh(&d->lock); ··· 339 257 int tipc_disc_create(struct net *net, struct tipc_bearer *b, 340 258 struct tipc_media_addr *dest, struct sk_buff **skb) 341 259 { 260 + struct tipc_net *tn = tipc_net(net); 342 261 struct tipc_discoverer *d; 343 262 344 263 d = kmalloc(sizeof(*d), GFP_ATOMIC); 345 264 if (!d) 346 265 return -ENOMEM; 347 - d->skb = tipc_buf_acquire(MAX_H_SIZE, GFP_ATOMIC); 266 + d->skb = tipc_buf_acquire(MAX_H_SIZE + NODE_ID_LEN, GFP_ATOMIC); 348 267 if (!d->skb) { 349 268 kfree(d); 350 269 return -ENOMEM; 351 270 } 352 - 353 271 tipc_disc_init_msg(net, d->skb, DSC_REQ_MSG, b); 272 + 273 + /* Do we need an address trial period first ? */ 274 + if (!tipc_own_addr(net)) { 275 + tn->addr_trial_end = jiffies + msecs_to_jiffies(1000); 276 + msg_set_type(buf_msg(d->skb), DSC_TRIAL_MSG); 277 + } 354 278 memcpy(&d->dest, dest, sizeof(*dest)); 355 279 d->net = net; 356 280 d->bearer_id = b->identity;
+17 -9
net/tipc/link.c
··· 434 434 */ 435 435 bool tipc_link_create(struct net *net, char *if_name, int bearer_id, 436 436 int tolerance, char net_plane, u32 mtu, int priority, 437 - int window, u32 session, u32 self, u32 peer, 438 - u16 peer_caps, 437 + int window, u32 session, u32 self, 438 + u32 peer, u8 *peer_id, u16 peer_caps, 439 439 struct tipc_link *bc_sndlink, 440 440 struct tipc_link *bc_rcvlink, 441 441 struct sk_buff_head *inputq, 442 442 struct sk_buff_head *namedq, 443 443 struct tipc_link **link) 444 444 { 445 - char *self_str = tipc_own_id_string(net); 445 + char peer_str[NODE_ID_STR_LEN] = {0,}; 446 + char self_str[NODE_ID_STR_LEN] = {0,}; 446 447 struct tipc_link *l; 447 448 448 449 l = kzalloc(sizeof(*l), GFP_ATOMIC); ··· 452 451 *link = l; 453 452 l->session = session; 454 453 455 - /* Note: peer i/f name is completed by reset/activate message */ 456 - if (strlen(self_str) > 16) 457 - sprintf(l->name, "%x:%s-%x:unknown", self, if_name, peer); 458 - else 459 - sprintf(l->name, "%s:%s-%x:unknown", self_str, if_name, peer); 454 + /* Set link name for unicast links only */ 455 + if (peer_id) { 456 + tipc_nodeid2string(self_str, tipc_own_id(net)); 457 + if (strlen(self_str) > 16) 458 + sprintf(self_str, "%x", self); 459 + tipc_nodeid2string(peer_str, peer_id); 460 + if (strlen(peer_str) > 16) 461 + sprintf(peer_str, "%x", peer); 462 + } 463 + /* Peer i/f name will be completed by reset/activate message */ 464 + sprintf(l->name, "%s:%s-%s:unknown", self_str, if_name, peer_str); 465 + 460 466 strcpy(l->if_name, if_name); 461 467 l->addr = peer; 462 468 l->peer_caps = peer_caps; ··· 511 503 struct tipc_link *l; 512 504 513 505 if (!tipc_link_create(net, "", MAX_BEARERS, 0, 'Z', mtu, 0, window, 514 - 0, ownnode, peer, peer_caps, bc_sndlink, 506 + 0, ownnode, peer, NULL, peer_caps, bc_sndlink, 515 507 NULL, inputq, namedq, link)) 516 508 return false; 517 509
+2 -2
net/tipc/link.h
··· 73 73 74 74 bool tipc_link_create(struct net *net, char *if_name, int bearer_id, 75 75 int tolerance, char net_plane, u32 mtu, int priority, 76 - int window, u32 session, u32 ownnode, u32 peer, 77 - u16 peer_caps, 76 + int window, u32 session, u32 ownnode, 77 + u32 peer, u8 *peer_id, u16 peer_caps, 78 78 struct tipc_link *bc_sndlink, 79 79 struct tipc_link *bc_rcvlink, 80 80 struct sk_buff_head *inputq,
+22 -1
net/tipc/msg.h
··· 550 550 */ 551 551 #define DSC_REQ_MSG 0 552 552 #define DSC_RESP_MSG 1 553 + #define DSC_TRIAL_MSG 2 554 + #define DSC_TRIAL_FAIL_MSG 3 553 555 554 556 /* 555 557 * Group protocol message types ··· 628 626 { 629 627 msg_set_bits(m, 2, 0, 0xffff, n); 630 628 } 631 - 632 629 633 630 /* 634 631 * Word 4 ··· 924 923 static inline bool msg_is_reset(struct tipc_msg *hdr) 925 924 { 926 925 return (msg_user(hdr) == LINK_PROTOCOL) && (msg_type(hdr) == RESET_MSG); 926 + } 927 + 928 + static inline u32 msg_sugg_node_addr(struct tipc_msg *m) 929 + { 930 + return msg_word(m, 14); 931 + } 932 + 933 + static inline void msg_set_sugg_node_addr(struct tipc_msg *m, u32 n) 934 + { 935 + msg_set_word(m, 14, n); 936 + } 937 + 938 + static inline void msg_set_node_id(struct tipc_msg *hdr, u8 *id) 939 + { 940 + memcpy(msg_data(hdr), id, 16); 941 + } 942 + 943 + static inline u8 *msg_node_id(struct tipc_msg *hdr) 944 + { 945 + return (u8 *)msg_data(hdr); 927 946 } 928 947 929 948 struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp);
+1 -3
net/tipc/net.c
··· 112 112 } 113 113 pr_info("Started in network mode\n"); 114 114 115 - if (node_id) { 115 + if (node_id) 116 116 tipc_set_node_id(net, node_id); 117 - tipc_net_finalize(net, tipc_own_addr(net)); 118 - } 119 117 if (addr) 120 118 tipc_net_finalize(net, addr); 121 119 return 0;
+78 -7
net/tipc/node.c
··· 115 115 u16 capabilities; 116 116 u32 signature; 117 117 u32 link_id; 118 + u8 peer_id[16]; 118 119 struct list_head publ_list; 119 120 struct list_head conn_sks; 120 121 unsigned long keepalive_intv; ··· 157 156 static void tipc_node_timeout(struct timer_list *t); 158 157 static void tipc_node_fsm_evt(struct tipc_node *n, int evt); 159 158 static struct tipc_node *tipc_node_find(struct net *net, u32 addr); 159 + static struct tipc_node *tipc_node_find_by_id(struct net *net, u8 *id); 160 160 static void tipc_node_put(struct tipc_node *node); 161 161 static bool node_is_up(struct tipc_node *n); 162 162 ··· 247 245 return node; 248 246 } 249 247 248 + /* tipc_node_find_by_id - locate specified node object by its 128-bit id 249 + * Note: this function is called only when a discovery request failed 250 + * to find the node by its 32-bit id, and is not time critical 251 + */ 252 + static struct tipc_node *tipc_node_find_by_id(struct net *net, u8 *id) 253 + { 254 + struct tipc_net *tn = tipc_net(net); 255 + struct tipc_node *n; 256 + bool found = false; 257 + 258 + rcu_read_lock(); 259 + list_for_each_entry_rcu(n, &tn->node_list, list) { 260 + read_lock_bh(&n->lock); 261 + if (!memcmp(id, n->peer_id, 16) && 262 + kref_get_unless_zero(&n->kref)) 263 + found = true; 264 + read_unlock_bh(&n->lock); 265 + if (found) 266 + break; 267 + } 268 + rcu_read_unlock(); 269 + return found ? n : NULL; 270 + } 271 + 250 272 static void tipc_node_read_lock(struct tipc_node *n) 251 273 { 252 274 read_lock_bh(&n->lock); ··· 333 307 } 334 308 } 335 309 336 - struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) 310 + struct tipc_node *tipc_node_create(struct net *net, u32 addr, 311 + u8 *peer_id, u16 capabilities) 337 312 { 338 313 struct tipc_net *tn = net_generic(net, tipc_net_id); 339 314 struct tipc_node *n, *temp_node; ··· 353 326 goto exit; 354 327 } 355 328 n->addr = addr; 329 + memcpy(&n->peer_id, peer_id, 16); 356 330 n->net = net; 357 331 n->capabilities = capabilities; 358 332 kref_init(&n->kref); ··· 372 344 n->signature = INVALID_NODE_SIG; 373 345 n->active_links[0] = INVALID_BEARER_ID; 374 346 n->active_links[1] = INVALID_BEARER_ID; 375 - if (!tipc_link_bc_create(net, tipc_own_addr(net), n->addr, 376 - U16_MAX, 347 + if (!tipc_link_bc_create(net, tipc_own_addr(net), 348 + addr, U16_MAX, 377 349 tipc_link_window(tipc_bc_sndlink(net)), 378 350 n->capabilities, 379 351 &n->bc_entry.inputq1, ··· 763 735 return retval; 764 736 } 765 737 766 - void tipc_node_check_dest(struct net *net, u32 onode, 767 - struct tipc_bearer *b, 738 + static u32 tipc_node_suggest_addr(struct net *net, u32 addr) 739 + { 740 + struct tipc_node *n; 741 + 742 + addr ^= tipc_net(net)->random; 743 + while ((n = tipc_node_find(net, addr))) { 744 + tipc_node_put(n); 745 + addr++; 746 + } 747 + return addr; 748 + } 749 + 750 + /* tipc_node_try_addr(): Check if addr can be used by peer, suggest other if not 751 + */ 752 + u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr) 753 + { 754 + struct tipc_net *tn = tipc_net(net); 755 + struct tipc_node *n; 756 + 757 + /* Suggest new address if some other peer is using this one */ 758 + n = tipc_node_find(net, addr); 759 + if (n) { 760 + if (!memcmp(n->peer_id, id, NODE_ID_LEN)) 761 + addr = 0; 762 + tipc_node_put(n); 763 + if (!addr) 764 + return 0; 765 + return tipc_node_suggest_addr(net, addr); 766 + } 767 + 768 + /* Suggest previously used address if peer is known */ 769 + n = tipc_node_find_by_id(net, id); 770 + if (n) { 771 + addr = n->addr; 772 + tipc_node_put(n); 773 + } 774 + /* Even this node may be in trial phase */ 775 + if (tn->trial_addr == addr) 776 + return tipc_node_suggest_addr(net, addr); 777 + 778 + return addr; 779 + } 780 + 781 + void tipc_node_check_dest(struct net *net, u32 addr, 782 + u8 *peer_id, struct tipc_bearer *b, 768 783 u16 capabilities, u32 signature, 769 784 struct tipc_media_addr *maddr, 770 785 bool *respond, bool *dupl_addr) ··· 826 755 *dupl_addr = false; 827 756 *respond = false; 828 757 829 - n = tipc_node_create(net, onode, capabilities); 758 + n = tipc_node_create(net, addr, peer_id, capabilities); 830 759 if (!n) 831 760 return; 832 761 ··· 911 840 if (!tipc_link_create(net, if_name, b->identity, b->tolerance, 912 841 b->net_plane, b->mtu, b->priority, 913 842 b->window, mod(tipc_net(net)->random), 914 - tipc_own_addr(net), onode, 843 + tipc_own_addr(net), addr, peer_id, 915 844 n->capabilities, 916 845 tipc_bc_sndlink(n->net), n->bc_entry.link, 917 846 &le->inputq,
+2 -1
net/tipc/node.h
··· 60 60 #define INVALID_BEARER_ID -1 61 61 62 62 void tipc_node_stop(struct net *net); 63 - void tipc_node_check_dest(struct net *net, u32 onode, 63 + u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr); 64 + void tipc_node_check_dest(struct net *net, u32 onode, u8 *peer_id128, 64 65 struct tipc_bearer *bearer, 65 66 u16 capabilities, u32 signature, 66 67 struct tipc_media_addr *maddr,