diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/addr.c | 3 | ||||
-rw-r--r-- | net/tipc/bearer.c | 3 | ||||
-rw-r--r-- | net/tipc/core.c | 2 | ||||
-rw-r--r-- | net/tipc/core.h | 2 | ||||
-rw-r--r-- | net/tipc/discover.c | 126 | ||||
-rw-r--r-- | net/tipc/link.c | 26 | ||||
-rw-r--r-- | net/tipc/link.h | 4 | ||||
-rw-r--r-- | net/tipc/msg.h | 23 | ||||
-rw-r--r-- | net/tipc/net.c | 4 | ||||
-rw-r--r-- | net/tipc/node.c | 85 | ||||
-rw-r--r-- | net/tipc/node.h | 3 |
11 files changed, 236 insertions, 45 deletions
diff --git a/net/tipc/addr.c b/net/tipc/addr.c index 4841e98591d0..b88d48d00913 100644 --- a/net/tipc/addr.c +++ b/net/tipc/addr.c | |||
@@ -59,7 +59,7 @@ void tipc_set_node_id(struct net *net, u8 *id) | |||
59 | 59 | ||
60 | memcpy(tn->node_id, id, NODE_ID_LEN); | 60 | memcpy(tn->node_id, id, NODE_ID_LEN); |
61 | tipc_nodeid2string(tn->node_id_string, id); | 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 | pr_info("Own node identity %s, cluster identity %u\n", | 63 | pr_info("Own node identity %s, cluster identity %u\n", |
64 | tipc_own_id_string(net), tn->net_id); | 64 | tipc_own_id_string(net), tn->net_id); |
65 | } | 65 | } |
@@ -74,6 +74,7 @@ void tipc_set_node_addr(struct net *net, u32 addr) | |||
74 | sprintf(node_id, "%x", addr); | 74 | sprintf(node_id, "%x", addr); |
75 | tipc_set_node_id(net, node_id); | 75 | tipc_set_node_id(net, node_id); |
76 | } | 76 | } |
77 | tn->trial_addr = addr; | ||
77 | pr_info("32-bit node address hash set to %x\n", addr); | 78 | pr_info("32-bit node address hash set to %x\n", addr); |
78 | } | 79 | } |
79 | 80 | ||
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index a71f31879cb3..ae5b44ca1c1e 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -235,7 +235,6 @@ static int tipc_enable_bearer(struct net *net, const char *name, | |||
235 | { | 235 | { |
236 | struct tipc_net *tn = tipc_net(net); | 236 | struct tipc_net *tn = tipc_net(net); |
237 | struct tipc_bearer_names b_names; | 237 | struct tipc_bearer_names b_names; |
238 | u32 self = tipc_own_addr(net); | ||
239 | int with_this_prio = 1; | 238 | int with_this_prio = 1; |
240 | struct tipc_bearer *b; | 239 | struct tipc_bearer *b; |
241 | struct tipc_media *m; | 240 | struct tipc_media *m; |
@@ -244,7 +243,7 @@ static int tipc_enable_bearer(struct net *net, const char *name, | |||
244 | int res = -EINVAL; | 243 | int res = -EINVAL; |
245 | char *errstr = ""; | 244 | char *errstr = ""; |
246 | 245 | ||
247 | if (!self) { | 246 | if (!tipc_own_id(net)) { |
248 | errstr = "not supported in standalone mode"; | 247 | errstr = "not supported in standalone mode"; |
249 | res = -ENOPROTOOPT; | 248 | res = -ENOPROTOOPT; |
250 | goto rejected; | 249 | goto rejected; |
diff --git a/net/tipc/core.c b/net/tipc/core.c index e92fed49e095..52dfc51ac4d5 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -57,6 +57,8 @@ static int __net_init tipc_init_net(struct net *net) | |||
57 | 57 | ||
58 | tn->net_id = 4711; | 58 | tn->net_id = 4711; |
59 | tn->node_addr = 0; | 59 | tn->node_addr = 0; |
60 | tn->trial_addr = 0; | ||
61 | tn->addr_trial_end = 0; | ||
60 | memset(tn->node_id, 0, sizeof(tn->node_id)); | 62 | memset(tn->node_id, 0, sizeof(tn->node_id)); |
61 | memset(tn->node_id_string, 0, sizeof(tn->node_id_string)); | 63 | memset(tn->node_id_string, 0, sizeof(tn->node_id_string)); |
62 | tn->mon_threshold = TIPC_DEF_MON_THRESHOLD; | 64 | tn->mon_threshold = TIPC_DEF_MON_THRESHOLD; |
diff --git a/net/tipc/core.h b/net/tipc/core.h index eabad41cc832..d0f64ca62d02 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
@@ -82,6 +82,8 @@ extern int sysctl_tipc_named_timeout __read_mostly; | |||
82 | struct tipc_net { | 82 | struct tipc_net { |
83 | u8 node_id[NODE_ID_LEN]; | 83 | u8 node_id[NODE_ID_LEN]; |
84 | u32 node_addr; | 84 | u32 node_addr; |
85 | u32 trial_addr; | ||
86 | unsigned long addr_trial_end; | ||
85 | char node_id_string[NODE_ID_STR_LEN]; | 87 | char node_id_string[NODE_ID_STR_LEN]; |
86 | int net_id; | 88 | int net_id; |
87 | int random; | 89 | int random; |
diff --git a/net/tipc/discover.c b/net/tipc/discover.c index b4c4cd176b9b..e7655736abed 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/discover.c | 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 | * Copyright (c) 2005-2006, 2010-2011, Wind River Systems | 5 | * Copyright (c) 2005-2006, 2010-2011, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
@@ -78,34 +78,40 @@ struct tipc_discoverer { | |||
78 | * @b: ptr to bearer issuing message | 78 | * @b: ptr to bearer issuing message |
79 | */ | 79 | */ |
80 | static void tipc_disc_init_msg(struct net *net, struct sk_buff *skb, | 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 | struct tipc_net *tn = tipc_net(net); | 83 | struct tipc_net *tn = tipc_net(net); |
84 | u32 self = tipc_own_addr(net); | ||
85 | u32 dest_domain = b->domain; | 84 | u32 dest_domain = b->domain; |
86 | struct tipc_msg *hdr; | 85 | struct tipc_msg *hdr; |
87 | 86 | ||
88 | hdr = buf_msg(skb); | 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 | MAX_H_SIZE, dest_domain); | 89 | MAX_H_SIZE, dest_domain); |
90 | msg_set_size(hdr, MAX_H_SIZE + NODE_ID_LEN); | ||
91 | msg_set_non_seq(hdr, 1); | 91 | msg_set_non_seq(hdr, 1); |
92 | msg_set_node_sig(hdr, tn->random); | 92 | msg_set_node_sig(hdr, tn->random); |
93 | msg_set_node_capabilities(hdr, TIPC_NODE_CAPABILITIES); | 93 | msg_set_node_capabilities(hdr, TIPC_NODE_CAPABILITIES); |
94 | msg_set_dest_domain(hdr, dest_domain); | 94 | msg_set_dest_domain(hdr, dest_domain); |
95 | msg_set_bc_netid(hdr, tn->net_id); | 95 | msg_set_bc_netid(hdr, tn->net_id); |
96 | b->media->addr2msg(msg_media_addr(hdr), &b->addr); | 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 | struct tipc_media_addr *maddr, | 102 | struct tipc_media_addr *maddr, |
101 | struct tipc_bearer *b) | 103 | struct tipc_bearer *b) |
102 | { | 104 | { |
105 | struct tipc_msg *hdr; | ||
103 | struct sk_buff *skb; | 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 | if (!skb) | 109 | if (!skb) |
107 | return; | 110 | return; |
111 | hdr = buf_msg(skb); | ||
108 | tipc_disc_init_msg(net, skb, mtyp, b); | 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 | tipc_bearer_xmit_skb(net, b->identity, skb, maddr); | 115 | tipc_bearer_xmit_skb(net, b->identity, skb, maddr); |
110 | } | 116 | } |
111 | 117 | ||
@@ -126,6 +132,52 @@ static void disc_dupl_alert(struct tipc_bearer *b, u32 node_addr, | |||
126 | media_addr_str, b->name); | 132 | media_addr_str, b->name); |
127 | } | 133 | } |
128 | 134 | ||
135 | /* tipc_disc_addr_trial(): - handle an address uniqueness trial from peer | ||
136 | */ | ||
137 | bool tipc_disc_addr_trial_msg(struct tipc_discoverer *d, | ||
138 | struct tipc_media_addr *maddr, | ||
139 | struct tipc_bearer *b, | ||
140 | u32 dst, u32 src, | ||
141 | u32 sugg_addr, | ||
142 | u8 *peer_id, | ||
143 | int mtyp) | ||
144 | { | ||
145 | struct net *net = d->net; | ||
146 | struct tipc_net *tn = tipc_net(net); | ||
147 | bool trial = time_before(jiffies, tn->addr_trial_end); | ||
148 | u32 self = tipc_own_addr(net); | ||
149 | |||
150 | if (mtyp == DSC_TRIAL_FAIL_MSG) { | ||
151 | if (!trial) | ||
152 | return true; | ||
153 | |||
154 | /* Ignore if somebody else already gave new suggestion */ | ||
155 | if (dst != tn->trial_addr) | ||
156 | return true; | ||
157 | |||
158 | /* Otherwise update trial address and restart trial period */ | ||
159 | tn->trial_addr = sugg_addr; | ||
160 | msg_set_prevnode(buf_msg(d->skb), sugg_addr); | ||
161 | tn->addr_trial_end = jiffies + msecs_to_jiffies(1000); | ||
162 | return true; | ||
163 | } | ||
164 | |||
165 | /* Apply trial address if we just left trial period */ | ||
166 | if (!trial && !self) { | ||
167 | tipc_net_finalize(net, tn->trial_addr); | ||
168 | msg_set_type(buf_msg(d->skb), DSC_REQ_MSG); | ||
169 | } | ||
170 | |||
171 | if (mtyp != DSC_TRIAL_MSG) | ||
172 | return false; | ||
173 | |||
174 | sugg_addr = tipc_node_try_addr(net, peer_id, src); | ||
175 | if (sugg_addr) | ||
176 | tipc_disc_msg_xmit(net, DSC_TRIAL_FAIL_MSG, src, | ||
177 | self, sugg_addr, maddr, b); | ||
178 | return true; | ||
179 | } | ||
180 | |||
129 | /** | 181 | /** |
130 | * tipc_disc_rcv - handle incoming discovery message (request or response) | 182 | * tipc_disc_rcv - handle incoming discovery message (request or response) |
131 | * @net: applicable net namespace | 183 | * @net: applicable net namespace |
@@ -139,17 +191,27 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *skb, | |||
139 | struct tipc_msg *hdr = buf_msg(skb); | 191 | struct tipc_msg *hdr = buf_msg(skb); |
140 | u16 caps = msg_node_capabilities(hdr); | 192 | u16 caps = msg_node_capabilities(hdr); |
141 | bool legacy = tn->legacy_addr_format; | 193 | bool legacy = tn->legacy_addr_format; |
194 | u32 sugg = msg_sugg_node_addr(hdr); | ||
142 | u32 signature = msg_node_sig(hdr); | 195 | u32 signature = msg_node_sig(hdr); |
196 | u8 peer_id[NODE_ID_LEN] = {0,}; | ||
143 | u32 dst = msg_dest_domain(hdr); | 197 | u32 dst = msg_dest_domain(hdr); |
144 | u32 net_id = msg_bc_netid(hdr); | 198 | u32 net_id = msg_bc_netid(hdr); |
145 | u32 self = tipc_own_addr(net); | ||
146 | struct tipc_media_addr maddr; | 199 | struct tipc_media_addr maddr; |
147 | u32 src = msg_prevnode(hdr); | 200 | u32 src = msg_prevnode(hdr); |
148 | u32 mtyp = msg_type(hdr); | 201 | u32 mtyp = msg_type(hdr); |
149 | bool dupl_addr = false; | 202 | bool dupl_addr = false; |
150 | bool respond = false; | 203 | bool respond = false; |
204 | u32 self; | ||
151 | int err; | 205 | int err; |
152 | 206 | ||
207 | skb_linearize(skb); | ||
208 | hdr = buf_msg(skb); | ||
209 | |||
210 | if (caps & TIPC_NODE_ID128) | ||
211 | memcpy(peer_id, msg_node_id(hdr), NODE_ID_LEN); | ||
212 | else | ||
213 | sprintf(peer_id, "%x", src); | ||
214 | |||
153 | err = b->media->msg2addr(b, &maddr, msg_media_addr(hdr)); | 215 | err = b->media->msg2addr(b, &maddr, msg_media_addr(hdr)); |
154 | kfree_skb(skb); | 216 | kfree_skb(skb); |
155 | if (err || maddr.broadcast) { | 217 | if (err || maddr.broadcast) { |
@@ -161,6 +223,12 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *skb, | |||
161 | return; | 223 | return; |
162 | if (net_id != tn->net_id) | 224 | if (net_id != tn->net_id) |
163 | return; | 225 | return; |
226 | if (tipc_disc_addr_trial_msg(b->disc, &maddr, b, dst, | ||
227 | src, sugg, peer_id, mtyp)) | ||
228 | return; | ||
229 | self = tipc_own_addr(net); | ||
230 | |||
231 | /* Message from somebody using this node's address */ | ||
164 | if (in_own_node(net, src)) { | 232 | if (in_own_node(net, src)) { |
165 | disc_dupl_alert(b, self, &maddr); | 233 | disc_dupl_alert(b, self, &maddr); |
166 | return; | 234 | return; |
@@ -169,8 +237,7 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *skb, | |||
169 | return; | 237 | return; |
170 | if (!tipc_in_scope(legacy, b->domain, src)) | 238 | if (!tipc_in_scope(legacy, b->domain, src)) |
171 | return; | 239 | return; |
172 | 240 | tipc_node_check_dest(net, src, peer_id, b, caps, signature, | |
173 | tipc_node_check_dest(net, src, b, caps, signature, | ||
174 | &maddr, &respond, &dupl_addr); | 241 | &maddr, &respond, &dupl_addr); |
175 | if (dupl_addr) | 242 | if (dupl_addr) |
176 | disc_dupl_alert(b, src, &maddr); | 243 | disc_dupl_alert(b, src, &maddr); |
@@ -178,7 +245,7 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *skb, | |||
178 | return; | 245 | return; |
179 | if (mtyp != DSC_REQ_MSG) | 246 | if (mtyp != DSC_REQ_MSG) |
180 | return; | 247 | return; |
181 | tipc_disc_msg_xmit(net, DSC_RESP_MSG, src, self, &maddr, b); | 248 | tipc_disc_msg_xmit(net, DSC_RESP_MSG, src, self, 0, &maddr, b); |
182 | } | 249 | } |
183 | 250 | ||
184 | /* tipc_disc_add_dest - increment set of discovered nodes | 251 | /* tipc_disc_add_dest - increment set of discovered nodes |
@@ -216,9 +283,11 @@ void tipc_disc_remove_dest(struct tipc_discoverer *d) | |||
216 | static void tipc_disc_timeout(struct timer_list *t) | 283 | static void tipc_disc_timeout(struct timer_list *t) |
217 | { | 284 | { |
218 | struct tipc_discoverer *d = from_timer(d, t, timer); | 285 | struct tipc_discoverer *d = from_timer(d, t, timer); |
286 | struct tipc_net *tn = tipc_net(d->net); | ||
287 | u32 self = tipc_own_addr(d->net); | ||
219 | struct tipc_media_addr maddr; | 288 | struct tipc_media_addr maddr; |
220 | struct sk_buff *skb = NULL; | 289 | struct sk_buff *skb = NULL; |
221 | struct net *net; | 290 | struct net *net = d->net; |
222 | u32 bearer_id; | 291 | u32 bearer_id; |
223 | 292 | ||
224 | spin_lock_bh(&d->lock); | 293 | spin_lock_bh(&d->lock); |
@@ -228,16 +297,29 @@ static void tipc_disc_timeout(struct timer_list *t) | |||
228 | d->timer_intv = TIPC_DISC_INACTIVE; | 297 | d->timer_intv = TIPC_DISC_INACTIVE; |
229 | goto exit; | 298 | goto exit; |
230 | } | 299 | } |
300 | |||
301 | /* Did we just leave the address trial period ? */ | ||
302 | if (!self && !time_before(jiffies, tn->addr_trial_end)) { | ||
303 | self = tn->trial_addr; | ||
304 | tipc_net_finalize(net, self); | ||
305 | msg_set_prevnode(buf_msg(d->skb), self); | ||
306 | msg_set_type(buf_msg(d->skb), DSC_REQ_MSG); | ||
307 | } | ||
308 | |||
231 | /* Adjust timeout interval according to discovery phase */ | 309 | /* Adjust timeout interval according to discovery phase */ |
232 | d->timer_intv *= 2; | 310 | if (time_before(jiffies, tn->addr_trial_end)) { |
233 | if (d->num_nodes && d->timer_intv > TIPC_DISC_SLOW) | 311 | d->timer_intv = TIPC_DISC_INIT; |
234 | d->timer_intv = TIPC_DISC_SLOW; | 312 | } else { |
235 | else if (!d->num_nodes && d->timer_intv > TIPC_DISC_FAST) | 313 | d->timer_intv *= 2; |
236 | d->timer_intv = TIPC_DISC_FAST; | 314 | if (d->num_nodes && d->timer_intv > TIPC_DISC_SLOW) |
315 | d->timer_intv = TIPC_DISC_SLOW; | ||
316 | else if (!d->num_nodes && d->timer_intv > TIPC_DISC_FAST) | ||
317 | d->timer_intv = TIPC_DISC_FAST; | ||
318 | } | ||
319 | |||
237 | mod_timer(&d->timer, jiffies + d->timer_intv); | 320 | mod_timer(&d->timer, jiffies + d->timer_intv); |
238 | memcpy(&maddr, &d->dest, sizeof(maddr)); | 321 | memcpy(&maddr, &d->dest, sizeof(maddr)); |
239 | skb = skb_clone(d->skb, GFP_ATOMIC); | 322 | skb = skb_clone(d->skb, GFP_ATOMIC); |
240 | net = d->net; | ||
241 | bearer_id = d->bearer_id; | 323 | bearer_id = d->bearer_id; |
242 | exit: | 324 | exit: |
243 | spin_unlock_bh(&d->lock); | 325 | spin_unlock_bh(&d->lock); |
@@ -257,18 +339,24 @@ exit: | |||
257 | int tipc_disc_create(struct net *net, struct tipc_bearer *b, | 339 | int tipc_disc_create(struct net *net, struct tipc_bearer *b, |
258 | struct tipc_media_addr *dest, struct sk_buff **skb) | 340 | struct tipc_media_addr *dest, struct sk_buff **skb) |
259 | { | 341 | { |
342 | struct tipc_net *tn = tipc_net(net); | ||
260 | struct tipc_discoverer *d; | 343 | struct tipc_discoverer *d; |
261 | 344 | ||
262 | d = kmalloc(sizeof(*d), GFP_ATOMIC); | 345 | d = kmalloc(sizeof(*d), GFP_ATOMIC); |
263 | if (!d) | 346 | if (!d) |
264 | return -ENOMEM; | 347 | return -ENOMEM; |
265 | d->skb = tipc_buf_acquire(MAX_H_SIZE, GFP_ATOMIC); | 348 | d->skb = tipc_buf_acquire(MAX_H_SIZE + NODE_ID_LEN, GFP_ATOMIC); |
266 | if (!d->skb) { | 349 | if (!d->skb) { |
267 | kfree(d); | 350 | kfree(d); |
268 | return -ENOMEM; | 351 | return -ENOMEM; |
269 | } | 352 | } |
270 | |||
271 | tipc_disc_init_msg(net, d->skb, DSC_REQ_MSG, b); | 353 | tipc_disc_init_msg(net, d->skb, DSC_REQ_MSG, b); |
354 | |||
355 | /* Do we need an address trial period first ? */ | ||
356 | if (!tipc_own_addr(net)) { | ||
357 | tn->addr_trial_end = jiffies + msecs_to_jiffies(1000); | ||
358 | msg_set_type(buf_msg(d->skb), DSC_TRIAL_MSG); | ||
359 | } | ||
272 | memcpy(&d->dest, dest, sizeof(*dest)); | 360 | memcpy(&d->dest, dest, sizeof(*dest)); |
273 | d->net = net; | 361 | d->net = net; |
274 | d->bearer_id = b->identity; | 362 | d->bearer_id = b->identity; |
diff --git a/net/tipc/link.c b/net/tipc/link.c index bcd76b1e440c..1289b4ba404f 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -434,15 +434,16 @@ char *tipc_link_name(struct tipc_link *l) | |||
434 | */ | 434 | */ |
435 | bool tipc_link_create(struct net *net, char *if_name, int bearer_id, | 435 | bool tipc_link_create(struct net *net, char *if_name, int bearer_id, |
436 | int tolerance, char net_plane, u32 mtu, int priority, | 436 | int tolerance, char net_plane, u32 mtu, int priority, |
437 | int window, u32 session, u32 self, u32 peer, | 437 | int window, u32 session, u32 self, |
438 | u16 peer_caps, | 438 | u32 peer, u8 *peer_id, u16 peer_caps, |
439 | struct tipc_link *bc_sndlink, | 439 | struct tipc_link *bc_sndlink, |
440 | struct tipc_link *bc_rcvlink, | 440 | struct tipc_link *bc_rcvlink, |
441 | struct sk_buff_head *inputq, | 441 | struct sk_buff_head *inputq, |
442 | struct sk_buff_head *namedq, | 442 | struct sk_buff_head *namedq, |
443 | struct tipc_link **link) | 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 | struct tipc_link *l; | 447 | struct tipc_link *l; |
447 | 448 | ||
448 | l = kzalloc(sizeof(*l), GFP_ATOMIC); | 449 | l = kzalloc(sizeof(*l), GFP_ATOMIC); |
@@ -451,11 +452,18 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id, | |||
451 | *link = l; | 452 | *link = l; |
452 | l->session = session; | 453 | l->session = session; |
453 | 454 | ||
454 | /* Note: peer i/f name is completed by reset/activate message */ | 455 | /* Set link name for unicast links only */ |
455 | if (strlen(self_str) > 16) | 456 | if (peer_id) { |
456 | sprintf(l->name, "%x:%s-%x:unknown", self, if_name, peer); | 457 | tipc_nodeid2string(self_str, tipc_own_id(net)); |
457 | else | 458 | if (strlen(self_str) > 16) |
458 | sprintf(l->name, "%s:%s-%x:unknown", self_str, if_name, peer); | 459 | sprintf(self_str, "%x", self); |
460 | tipc_nodeid2string(peer_str, peer_id); | ||
461 | if (strlen(peer_str) > 16) | ||
462 | sprintf(peer_str, "%x", peer); | ||
463 | } | ||
464 | /* Peer i/f name will be completed by reset/activate message */ | ||
465 | sprintf(l->name, "%s:%s-%s:unknown", self_str, if_name, peer_str); | ||
466 | |||
459 | strcpy(l->if_name, if_name); | 467 | strcpy(l->if_name, if_name); |
460 | l->addr = peer; | 468 | l->addr = peer; |
461 | l->peer_caps = peer_caps; | 469 | l->peer_caps = peer_caps; |
@@ -503,7 +511,7 @@ bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer, | |||
503 | struct tipc_link *l; | 511 | struct tipc_link *l; |
504 | 512 | ||
505 | if (!tipc_link_create(net, "", MAX_BEARERS, 0, 'Z', mtu, 0, window, | 513 | if (!tipc_link_create(net, "", MAX_BEARERS, 0, 'Z', mtu, 0, window, |
506 | 0, ownnode, peer, peer_caps, bc_sndlink, | 514 | 0, ownnode, peer, NULL, peer_caps, bc_sndlink, |
507 | NULL, inputq, namedq, link)) | 515 | NULL, inputq, namedq, link)) |
508 | return false; | 516 | return false; |
509 | 517 | ||
diff --git a/net/tipc/link.h b/net/tipc/link.h index d1bd1787a768..ec59348a81e8 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h | |||
@@ -73,8 +73,8 @@ enum { | |||
73 | 73 | ||
74 | bool tipc_link_create(struct net *net, char *if_name, int bearer_id, | 74 | bool tipc_link_create(struct net *net, char *if_name, int bearer_id, |
75 | int tolerance, char net_plane, u32 mtu, int priority, | 75 | int tolerance, char net_plane, u32 mtu, int priority, |
76 | int window, u32 session, u32 ownnode, u32 peer, | 76 | int window, u32 session, u32 ownnode, |
77 | u16 peer_caps, | 77 | u32 peer, u8 *peer_id, u16 peer_caps, |
78 | struct tipc_link *bc_sndlink, | 78 | struct tipc_link *bc_sndlink, |
79 | struct tipc_link *bc_rcvlink, | 79 | struct tipc_link *bc_rcvlink, |
80 | struct sk_buff_head *inputq, | 80 | struct sk_buff_head *inputq, |
diff --git a/net/tipc/msg.h b/net/tipc/msg.h index b4ba1b4f9ae7..a4e944d59394 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h | |||
@@ -550,6 +550,8 @@ static inline void msg_set_nameupper(struct tipc_msg *m, u32 n) | |||
550 | */ | 550 | */ |
551 | #define DSC_REQ_MSG 0 | 551 | #define DSC_REQ_MSG 0 |
552 | #define DSC_RESP_MSG 1 | 552 | #define DSC_RESP_MSG 1 |
553 | #define DSC_TRIAL_MSG 2 | ||
554 | #define DSC_TRIAL_FAIL_MSG 3 | ||
553 | 555 | ||
554 | /* | 556 | /* |
555 | * Group protocol message types | 557 | * Group protocol message types |
@@ -627,7 +629,6 @@ static inline void msg_set_bcgap_to(struct tipc_msg *m, u32 n) | |||
627 | msg_set_bits(m, 2, 0, 0xffff, n); | 629 | msg_set_bits(m, 2, 0, 0xffff, n); |
628 | } | 630 | } |
629 | 631 | ||
630 | |||
631 | /* | 632 | /* |
632 | * Word 4 | 633 | * Word 4 |
633 | */ | 634 | */ |
@@ -925,6 +926,26 @@ static inline bool msg_is_reset(struct tipc_msg *hdr) | |||
925 | return (msg_user(hdr) == LINK_PROTOCOL) && (msg_type(hdr) == RESET_MSG); | 926 | return (msg_user(hdr) == LINK_PROTOCOL) && (msg_type(hdr) == RESET_MSG); |
926 | } | 927 | } |
927 | 928 | ||
929 | static inline u32 msg_sugg_node_addr(struct tipc_msg *m) | ||
930 | { | ||
931 | return msg_word(m, 14); | ||
932 | } | ||
933 | |||
934 | static inline void msg_set_sugg_node_addr(struct tipc_msg *m, u32 n) | ||
935 | { | ||
936 | msg_set_word(m, 14, n); | ||
937 | } | ||
938 | |||
939 | static inline void msg_set_node_id(struct tipc_msg *hdr, u8 *id) | ||
940 | { | ||
941 | memcpy(msg_data(hdr), id, 16); | ||
942 | } | ||
943 | |||
944 | static inline u8 *msg_node_id(struct tipc_msg *hdr) | ||
945 | { | ||
946 | return (u8 *)msg_data(hdr); | ||
947 | } | ||
948 | |||
928 | struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp); | 949 | struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp); |
929 | bool tipc_msg_validate(struct sk_buff **_skb); | 950 | bool tipc_msg_validate(struct sk_buff **_skb); |
930 | bool tipc_msg_reverse(u32 own_addr, struct sk_buff **skb, int err); | 951 | bool tipc_msg_reverse(u32 own_addr, struct sk_buff **skb, int err); |
diff --git a/net/tipc/net.c b/net/tipc/net.c index e78674891166..29538dc00857 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
@@ -112,10 +112,8 @@ int tipc_net_init(struct net *net, u8 *node_id, u32 addr) | |||
112 | } | 112 | } |
113 | pr_info("Started in network mode\n"); | 113 | pr_info("Started in network mode\n"); |
114 | 114 | ||
115 | if (node_id) { | 115 | if (node_id) |
116 | tipc_set_node_id(net, node_id); | 116 | tipc_set_node_id(net, node_id); |
117 | tipc_net_finalize(net, tipc_own_addr(net)); | ||
118 | } | ||
119 | if (addr) | 117 | if (addr) |
120 | tipc_net_finalize(net, addr); | 118 | tipc_net_finalize(net, addr); |
121 | return 0; | 119 | return 0; |
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, |
diff --git a/net/tipc/node.h b/net/tipc/node.h index e06faf4fa55e..f24b83500df1 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
@@ -60,7 +60,8 @@ enum { | |||
60 | #define INVALID_BEARER_ID -1 | 60 | #define INVALID_BEARER_ID -1 |
61 | 61 | ||
62 | void tipc_node_stop(struct net *net); | 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 | struct tipc_bearer *bearer, | 65 | struct tipc_bearer *bearer, |
65 | u16 capabilities, u32 signature, | 66 | u16 capabilities, u32 signature, |
66 | struct tipc_media_addr *maddr, | 67 | struct tipc_media_addr *maddr, |